/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package Negocio;

import Util.GestorConfiguracion;
import Util.GestorErrores;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Esta clase implementa la gestión de una solicitud de préstamo.
 * Es una subclase de DatosPrestamo
 * @author Javi
 */
public class SolicitudPrestamo extends DatosPrestamo {

    public SolicitudPrestamo (){
        this.setsDescripTabla ("Solicitudes de Préstamo");
        this.setbConcedido(false);
    }

    public void inicializa (){
        //Inicialización de DatosPrestamo
        super.inicializa();
        //Inicializamos la variable que indica si es un Préstamo o solicitud préstamo
        this.getoCompra().setbConcedido(false);
        //En la solicitud de préstamo por defecto está pendiente de evaluación
        this.getoCompra().setsAutorizada("2");
        //En la solicitud la morosidad por defecto va como "0 - Sin valorar"
        this.getoCompra().setsEstudioMorosidad("0");
    }


    /**
     * Pasa una solicitud de préstamo a préstamo concedido
     * La solicitud debe estar AUTORIZADA previamente (autorizada = true)
     * @return
     */
    public boolean conceder (){
        if ( !validarConcesion() )
            return false;
        //Actualizo los atributos necesarios para convertirlo en un préstamo
        //Inicializamos la variable que indica si es un Prestamo o solicitud préstamo
        this.getoCompra().setbConcedido(true);
        //En un Préstamo la solicitud de préstamo tuvo que ser autorizada
        this.getoCompra().setsAutorizada("1");
        //En el préstamo la morosidad por defecto es: 0 - Sin valorar
        this.getoCompra().setsEstudioMorosidad("0");
        //Actualizo solamente en la TABLA DE Compras poniendo el campo Concedido = true
        return this.getoCompra().update();
    }

    /*
     * Valida que la solicitud esté autorizada previamente.
     *
     */
    public boolean validarConcesion (){
        boolean bOK = true;
        if ( ! (this.getoCompra().getsAutorizada().compareTo("1")== 0) ){
            GestorErrores.getInstancia().getvErrores().add ("La solicitud debe ser autorizada previamente a la concesión del préstamo");
            bOK = false;
        }
        //Llamo al validar de esta clase
        return ( bOK & this.validar() );
    }

    /**
     * Se añade una validación adicional: Una solicitud de préstamo solo puede estar en estado
     * "autorizada" (para su conversión en préstamo) si la morosidad se encuentra dentro del umbral permitido.
     * @return
     */
    public boolean validar (){
        boolean bOK = true;
        String sMensaje;
        //SI NO SE HA OBTENIDO UN VALOR DE MOROSIDAD (ES 0) NO SE VALIDA EL CAMPO AUTORIZACION
        if (this.getoCompra().getfProbMorosidad() != 0){
            //Validar que si se supera el umbral mínimo para denegación la solicitud queda como denegada.
            if ( this.getoCompra().getfProbMorosidad() >
                    Integer.parseInt( GestorConfiguracion.getInstancia().getProperty(GestorConfiguracion.MIN_DENEGA_AUTO)) &&
                    this.getoCompra().getsAutorizada().compareTo("0") != 0) {
                sMensaje = "La solicitud debe denegarse ya que se ha superado el umbral de morosidad permitido (";
                sMensaje += GestorConfiguracion.getInstancia().getProperty(GestorConfiguracion.MIN_DENEGA_AUTO) + "%)";
                GestorErrores.getInstancia().getvErrores().add (sMensaje);
                bOK = false;
            }
            //Validar que si no se llega al umbral máximo para autorización automática la solicitud queda como autorizada.
            if ( this.getoCompra().getfProbMorosidad() <
                    Integer.parseInt( GestorConfiguracion.getInstancia().getProperty(GestorConfiguracion.MAX_AUTORIZ_AUTO)) &&
                    this.getoCompra().getsAutorizada().compareTo("1") != 0 ) {
                sMensaje = "La solicitud debe autorizarse ya que está por debajo del umbral máximo para la autorización automática (";
                sMensaje += GestorConfiguracion.getInstancia().getProperty(GestorConfiguracion.MAX_AUTORIZ_AUTO) + "%)";
                GestorErrores.getInstancia().getvErrores().add (sMensaje);
                bOK = false;
            }
        }
        //Llamo a la validación de la clase padre
        return bOK & super.validar();
    }

    public void setsAutorizada(float fProbMorosidad) {
        //ESTABLECER valor del CAMPO AUTORIZACIÓN
        //LA solicitud automáticamente SE DENIEGA si se supera el umbral máximo permitido para la morosidad.
        if (fProbMorosidad >
                Integer.parseInt( GestorConfiguracion.getInstancia().getProperty(GestorConfiguracion.MIN_DENEGA_AUTO)) )
            this.getoCompra().setsAutorizada("0");
        else
            //La solicitud automáticamente SE AUTORIZA si no se llega al Umbral mínimo de morosidad
            if (fProbMorosidad <
                Integer.parseInt( GestorConfiguracion.getInstancia().getProperty(GestorConfiguracion.MAX_AUTORIZ_AUTO)) )
                this.getoCompra().setsAutorizada("1");
            else    //En cuqluier otro caso queda como pendiente de valoración
                this.getoCompra().setsAutorizada("2");
    }


//    public boolean evaluaRegla ( Regla oRegla ){
//        boolean bResultado = true;
//        //Si la regla no tiene premisas se devuelve falso.
//        if ( oRegla.getAoPremisas().size() == 0)
//            return false;
//        for (int i= 0; i < oRegla.getAoPremisas().size(); i++)
//            if (! evaluaPremisa (oRegla.getAoPremisas().get(i)) )
//                return false;
//        return true;
//    }

    /**
     * Evalúa la premisa recibida y devuelve verdadero o falso en función de si se cumple o no.
     * Tiene en cuenta el tipo de premisa, positiva o negativa
     * @param oPremisa
     * @return
     */
    public boolean evaluaPremisa ( Premisa oPremisa ){
        boolean bCumple =  evaluaPremisaPositiva ( oPremisa );
        if (oPremisa.getsTipoPremisa().equals("P"))
            return bCumple;
        else if (oPremisa.getsTipoPremisa().equals("N"))
            return !bCumple;
        else
            return false;
    }

    /**
     * Evalúa la premisa recibida y devuelve verdadero o falso en función de si se cumple o no.
     * NO tiene en cuenta el tipo de premisa, positiva o negativa
     * @param oPremisa
     * @return
     */
    private boolean evaluaPremisaPositiva ( Premisa oPremisa ){
        //Campos de la tabla de ClienteDatPErs
        if ( oPremisa.getsTabla().equalsIgnoreCase ("ClienteDatPers")){
            if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("FechaNacimiento"))
                return evaluaCampoFecha(this.getoCliente().getoClienteDatPers().getdFechaNacimiento(), oPremisa);
            else if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("Sexo"))
                return evaluaCampoString(this.getoCliente().getoClienteDatPers().getsSexo(), oPremisa);
            else if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("Nacionalidad"))
                return evaluaCampoString(this.getoCliente().getoClienteDatPers().getsNacionalidad(), oPremisa);
            else if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("Extranjero"))
                return evaluaCampoBoolean(this.getoCliente().getoClienteDatPers().getbExtranjero(), oPremisa);
            else if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("NivelEstudios"))
                return evaluaCampoString(this.getoCliente().getoClienteDatPers().getsNivelEstudios(), oPremisa);
            else if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("PermisoResidencia"))
                return evaluaCampoBoolean(this.getoCliente().getoClienteDatPers().getbPermisoResidencia(), oPremisa);
            else if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("AniosResidencia"))
                return evaluaCampoInteger(this.getoCliente().getoClienteDatPers().getiAniosResidencia(), oPremisa);
        //Campos de la tabla de ClienteDatSociales
        }else if ( oPremisa.getsTabla().trim().equalsIgnoreCase ("ClienteDatSociales") ){
            if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("EstadoCivil"))
                return evaluaCampoString(this.getoCliente().getoClienteDatSoc().getsEstadoCivil(), oPremisa);
            else if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("NumHijosPersonas"))
                return evaluaCampoInteger(this.getoCliente().getoClienteDatSoc().getiNumHijosPersonas(), oPremisa);
        //Campos de la tabla de ClienteDatSocioEco
        }else if ( oPremisa.getsTabla().trim().equalsIgnoreCase ("ClienteDatSocioEco") ){
            if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("CodProfesion"))
                return evaluaCampoString(this.getoCliente().getoClienteDatSocEco().getsCodProfesion(), oPremisa);
            else if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("CodSitLaboral"))
                return evaluaCampoString(this.getoCliente().getoClienteDatSocEco().getsCodSitLaboral(), oPremisa);
            else if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("CodActivEmp"))
                return evaluaCampoString(this.getoCliente().getoClienteDatSocEco().getsCodActivEmp(), oPremisa);
            else if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("CargoEmp"))
                return evaluaCampoString(this.getoCliente().getoClienteDatSocEco().getsCargoEmp(), oPremisa);
            else if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("Antiguedad"))
                return evaluaCampoInteger(this.getoCliente().getoClienteDatSocEco().getiAntiguedad(), oPremisa);
            else if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("CambiosTrabajo"))
                return evaluaCampoInteger(this.getoCliente().getoClienteDatSocEco().getiCambiosTrabajo(), oPremisa);
            else if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("SueldoAnuFijo"))
                return evaluaCampoInteger(this.getoCliente().getoClienteDatSocEco().getiSueldoAnuFijo(), oPremisa);
            else if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("SueldoAnuVar"))
                return evaluaCampoInteger(this.getoCliente().getoClienteDatSocEco().getiSueldoAnuVar(), oPremisa);
            else if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("OtrosIngresosAnu"))
                return evaluaCampoInteger(this.getoCliente().getoClienteDatSocEco().getiOtrosIngresosAnu(), oPremisa);
            else if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("ImpGastosMen"))
                return evaluaCampoInteger(this.getoCliente().getoClienteDatSocEco().getiImpGastosMen(), oPremisa);
            else if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("ImpHipAlqMen"))
                return evaluaCampoInteger(this.getoCliente().getoClienteDatSocEco().getiImpHipAlqMen(), oPremisa);
            else if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("CoefCajaMen"))
                return evaluaCampoInteger(this.getoCliente().getoClienteDatSocEco().getiCoefCajaMen(), oPremisa);
            else if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("ViviendaPropia"))
                return evaluaCampoBoolean(this.getoCliente().getoClienteDatSocEco().isbViviendaPropia(), oPremisa);
            else if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("ValorVivienda"))
                return evaluaCampoInteger(this.getoCliente().getoClienteDatSocEco().getiValorVivienda(), oPremisa);
            else if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("OtrasProp"))
                return evaluaCampoBoolean(this.getoCliente().getoClienteDatSocEco().isbOtrasProp(), oPremisa);
            else if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("ValorOtrasProp"))
                return evaluaCampoInteger(this.getoCliente().getoClienteDatSocEco().getiValorOtrasProp(), oPremisa);
        //Campos de la tabla de ClienteHobbies
        }else if ( oPremisa.getsTabla().trim().equalsIgnoreCase ("Clientehobbies") ){
            if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("CodHobby")){
                //La condición se cumple si alguno de los hobbys que tiene el cliente es el buscado
                for (int i=0; i < this.getoCliente().getoClienteHob().getasCodHobby().size(); i++)
                    if (evaluaCampoString(this.getoCliente().getoClienteHob().getasCodHobby().get(i), oPremisa))
                        return true;
                return false;
            }
        //Campos de la tabla Compra
        }else if ( oPremisa.getsTabla().trim().equalsIgnoreCase ("Compra") ){
            if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("TipoFinan"))
                return evaluaCampoString(this.getoCompra().getsTipoFinan(), oPremisa);
            else if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("AniosPago"))
                return evaluaCampoInteger(this.getoCompra().getiAniosPago(), oPremisa);
            else if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("ImporteMensual"))
                return evaluaCampoInteger(this.getoCompra().getiImporteMensual(), oPremisa);
            else if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("TipoInteres"))
                return evaluaCampoString(this.getoCompra().getsTipoInteres(), oPremisa);
        //Campos de la tabla Bien
        }else if ( oPremisa.getsTabla().trim().equalsIgnoreCase ("Bienes") ){
            if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("Tipo"))
                return evaluaCampoString(this.getoBien().getsTipo(), oPremisa);
            else if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("SubTipo"))
                return evaluaCampoString(this.getoBien().getsSubTipo(), oPremisa);
            else if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("Importe"))
                return evaluaCampoInteger(this.getoBien().getiImporte(), oPremisa);
            else if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("CodZona"))
                return evaluaCampoString(this.getoBien().getsCodZona(), oPremisa);
            else if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("CodCilindrada"))
                return evaluaCampoString(this.getoBien().getsCodCilindrada(), oPremisa);
            else if ( oPremisa.getsCampo().trim().equalsIgnoreCase ("CodUso"))
                return evaluaCampoString(this.getoBien().getsCodUso(), oPremisa);
        }
        //Si no es ninguna de ellas devolver falso.
        return false;
    }

    public boolean evaluaCampoString( String sCampo, Premisa oPremisa){
        //Valida contra oPremisa.Valor, oPremisa.ValorMin y oPremisa.ValorMax
        if ( !oPremisa.getsValor().trim().equals("") )
            return (sCampo.trim().equalsIgnoreCase(oPremisa.getsValor().trim()));
        else{
            boolean bCumpleMin, bCumpleMax;
            bCumpleMin = false;
            bCumpleMax = false;
            if ( sCampo.trim().compareTo(oPremisa.getsValorMin().trim()) >= 0)
                bCumpleMin = true;
            if ( sCampo.trim().compareTo(oPremisa.getsValorMax().trim()) <= 0)
                bCumpleMax = true;
            return bCumpleMin && bCumpleMax;
        }
    }

    public boolean evaluaCampoBoolean( boolean bCampo, Premisa oPremisa){
        //Valida contra oPremisa.Valor
        return ( (bCampo && (oPremisa.getsValor().trim().equals("S"))) ||
                (!bCampo && (oPremisa.getsValor().trim().equals("N"))) );
    }

    public boolean evaluaCampoInteger ( int iCampo, Premisa oPremisa) {
        //Valida contra  oPremisa.VAlor, oPremisa.iValorMin y oPremisa.iValorMax
        if ( !oPremisa.getsValor().trim().equals("") )
            return (iCampo == Integer.parseInt(oPremisa.getsValor().trim()));
        else{
            boolean bCumpleMin, bCumpleMax;
            bCumpleMin = false;
            bCumpleMax = false;
            if ( iCampo >= Integer.parseInt(oPremisa.getsValorMin().trim()) )
                bCumpleMin = true;
            if ( iCampo <= Integer.parseInt(oPremisa.getsValorMax().trim()) )
                bCumpleMax = true;
            return bCumpleMin && bCumpleMax;
        }
    }

    public boolean evaluaCampoFecha (Date dCampo, Premisa oPremisa){
        SimpleDateFormat formatoDelTexto = new SimpleDateFormat("dd/MM/yyyy");
        Date dFecha1 = new Date();
        Date dFecha2 = new Date();

        //Valida contra  oPremisa.VAlor, oPremisa.iValorMin y oPremisa.iValorMax
        if ( !oPremisa.getsValor().trim().equals("") ){
            try {
                dFecha1 = formatoDelTexto.parse( oPremisa.getsValor().trim() );
            } catch (ParseException ex) {
                return false;
            }
            return ( dCampo.compareTo(dFecha1) == 0 );
        }else{
            try {
                dFecha1 = formatoDelTexto.parse( oPremisa.getsValorMin().trim() );
            } catch (ParseException ex) {
                return false;
            }
            try {
                dFecha2 = formatoDelTexto.parse( oPremisa.getsValorMax().trim() );
            } catch (ParseException ex) {
                return false;
            }
            return ( (dCampo.compareTo(dFecha1) >= 0)  && (dCampo.compareTo(dFecha2) <= 0) );
        }
    }
}
